#include "server.h"

int flag = 1;
// 存储指向客户端结构体的指针的数组
static TCP_fd *clients[MAX_CLIENTS]; // 存储客户端的数组
static int client_count = 0;         // 连接的客户端数量
static pthread_mutex_t client_mutex; // 用于线程安全访问客户端数据的互斥锁
struct sockaddr_in addr;             // 地址结构
int addrlen = sizeof(addr);          // 地址结构长度

TCP_fd TCP_init(char const *port_num, char const  *IP_addr, TCP_fd fd) // 初始化TCP套接字
{

    pthread_mutex_init(&client_mutex, NULL); // 初始化互斥锁

    // 创建套接字
    if ((fd.soc_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port_num));
    addr.sin_addr.s_addr = inet_addr(IP_addr);

    // 将套接字绑定到地址
    if (bind(fd.soc_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("Bind failed");
        close(fd.soc_fd);
        exit(EXIT_FAILURE);
    }

    // 监听客户端连接
    if (listen(fd.soc_fd, MAX_CLIENTS) < 0)
    {
        perror("Listen failed");
        close(fd.soc_fd);
        exit(EXIT_FAILURE);
    }
    printf("服务启动成功，进入监听状态\n"); // 打印消息表示服务器正在运行并监听客户端连接
    return fd;
}

TCP_fd TCP_accept(TCP_fd fd) // 接受传入的客户端连接
{
    // 接受传入的客户端连接
    struct sockaddr_in client_addr;
    if ((fd.acc_fd = accept(fd.soc_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addrlen)) < 0)
    {
        perror("Accept failed");
    }
    return fd;
}

// 广播消息给所有连接的客户端
void broadcast_message(const char *message)
{
    pthread_mutex_lock(&client_mutex); // 锁定互斥锁以防止并发访问客户端数据
    for (int i = 0; i < client_count; i++)
    {
        send(clients[i]->acc_fd, message, strlen(message), 0); // 向每个客户端发送消息
    }
    pthread_mutex_unlock(&client_mutex); // 广播消息后解锁互斥锁
}

// 处理与客户端通信的函数，在单独的线程中运行
void *handle_client(void *client_socket)
{
    TCP_fd *client = (TCP_fd *)client_socket;
    char buffer[BUFFER_SIZE]; // 用于存储接收到的消息
    int bytes_read;           // 接收到的字节数

    // 接收来自客户端的消息，直到连接关闭
    while ((bytes_read = recv(client->acc_fd, buffer, BUFFER_SIZE, 0)) > 0)
    {
        buffer[bytes_read] = '\0';                // 给接收到的消息添加空字符终止符
        printf("%s: %s\n", client->name, buffer); // 在服务器控制台上打印客户端的名称和消息

        // 创建要广播给所有客户端（包括发送者）的消息
        char *message = (char *)malloc(strlen(client->name) + strlen(buffer) + 4);
        sprintf(message, "%s: %s", client->name, buffer);
        broadcast_message(message); // 广播消息给所有客户端
        free(message);              // 释放为消息分配的内存
    }

    printf("%s 已退出聊天室\n", client->name); // 当客户端断开连接时打印消息

    // 关闭客户端套接字并从数组中移除客户端
    pthread_mutex_lock(&client_mutex); // 锁定互斥锁以安全地访问客户端数据
    close(client->acc_fd);             // 关闭客户端套接字
    for (int i = 0; i < client_count; i++)
    {
        if (clients[i]->acc_fd == client->acc_fd)
        {
            // 通过移动后续元素来从数组中移除客户端
            for (int j = i; j < client_count - 1; j++)
            {
                clients[j] = clients[j + 1];
            }
            client_count--; // 减少客户端数量
            break;
        }
    }
    free(client);                        // 释放为客户端结构体分配的内存
    pthread_mutex_unlock(&client_mutex); // 修改客户端数据后解锁互斥锁

    pthread_exit(NULL); // 退出线程
}

// 修改客户端数据
void rece_pack(TCP_fd *fd)
{
    pthread_mutex_lock(&client_mutex); // 锁定互斥锁以安全地访问客户端数据
    if (client_count < MAX_CLIENTS)
    {
        // 为客户端结构体分配内存
        fd = (TCP_fd *)malloc(sizeof(TCP_fd));
        // 接收客户端的名称
        recv(fd->acc_fd, fd->name, NAME_SIZE, 0);

        // 初始化客户端结构体并添加到数组中
        clients[client_count] = fd;

        printf("%s 进入聊天室\n", fd->name); // 打印消息表示客户端已加入

        client_count++; // 增加客户端数量
        // 创建线程来处理客户端通信
        pthread_t thread;
        pthread_create(&thread, NULL, handle_client, fd);
        pthread_detach(thread); // 分离线程以允许其独立运行
    }
    else
    {
        printf("Maximum clients conneted. Connection refused.\n"); // 如果达到最大客户端数量则打印消息
        close(fd->acc_fd);                                         // 关闭客户端套接字
    }
    pthread_mutex_unlock(&client_mutex); // 修改客户端数据后解锁互斥锁
}

// 数据发送
void *send_pack(void *acc_fd)
{
}

// 多线程
int thread_send_rece(int acc_fd)
{
}

void TCP_close(TCP_fd fd)
{
    close(fd.acc_fd);
    close(fd.soc_fd);
}
